<template>
  <div class="virtual-scroll-checkout" :style="{ height: getHeight }">
    <!-- 左列虚拟列表 -->
    <div class="scroller-left" v-loading="loading">
      <div class="scroller-list" @scroll="handleScroll" ref="scrollContainer">
        <el-checkbox
          v-for="item in items"
          :key="item[keyField]"
          class="scroller-list-item"
          :model-value="checkItemsMap[item[keyField]]"
          @change="onItemChange(item)"
        >
          <template v-if="$slots.default">
            <slot :item="item">
              {{ item.title }}
            </slot>
          </template>
          <template v-else>
            <slot name="left" :item="item">
              {{ item.title }}
            </slot>
          </template>
        </el-checkbox>
      </div>
    </div>

    <!-- 右列虚拟列表 -->
    <div class="scroller-right">
      <div class="is-title scroller-title">已选中</div>

      <div class="scroller-list">
        <div
          v-for="item in cacheCheckItems"
          :key="item[keyField]"
          class="scroller-list-item scroller-right-item"
        >
          <div class="scroller-right-item--left">
            <template v-if="$slots.default">
              <slot :item="item">
                {{ item.title }}
              </slot>
            </template>
            <template v-else>
              <slot name="right" :item="item">
                {{ item.title }}
              </slot>
            </template>
          </div>
          <el-icon class="scroller-right-item--close" @click="onItemClose(item)">
            <Close />
          </el-icon>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup name="virtual-scroll-checkout">
import { computed, nextTick, ref, watchEffect } from 'vue';
import { Close } from '@element-plus/icons-vue';
import { RecycleScroller } from 'vue-virtual-scroller';
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css';

const emit = defineEmits(['update:checkItems', 'on-scroll-end']);

const props = defineProps({
  // 待选择数据
  items: {
    type: Array,
    default: () => [],
  },

  // id字段名
  keyField: {
    type: String,
    default: 'id',
  },

  // 每一项高度大小
  itemSize: {
    type: Number,
    default: 50,
  },

  // 整体高度
  height: {
    type: Number,
    default: 520,
  },

  // 已选中数据
  checkItems: {
    type: Array,
    default: () => [],
  },

  // loading
  loading: {
    type: Boolean,
    default: false,
  },
});

const getHeight = computed(() =>
  typeof props.height == 'string' ? props.height : `${props.height}px`,
);

// 是否全选
const isAllChecked = computed(() => cacheCheckItems.value.length === props.items.length);

// 部分数据勾选状态
const isIndeterminate = computed(() =>
  isAllChecked.value ? false : cacheCheckItems.value.length > 0,
);

// 是否选择字典
const checkItemsMap = ref({});

// 已选择暂存数据
const cacheCheckItems = ref(props.checkItems);

// 是否执行watchEffect里的计算
let isEffect = true;

watchEffect(() => {
  if (isEffect) {
    console.log('checkItems更新');
    console.log('items更新');

    cacheCheckItems.value = props.checkItems;

    for (const item of props.items) {
      checkItemsMap.value[item[props.keyField]] = false;
    }

    for (const item of props.checkItems) {
      checkItemsMap.value[item[props.keyField]] = true;
    }
  }
});

const onItemChange = (item) => {
  let status = checkItemsMap.value[item[props.keyField]];

  checkItemsMap.value[item[props.keyField]] = !status;

  let index = cacheCheckItems.value.findIndex((v) => v[props.keyField] == item[props.keyField]);

  if (index === -1) {
    cacheCheckItems.value = cacheCheckItems.value.concat([item]);
  } else {
    cacheCheckItems.value.splice(index, 1);
    cacheCheckItems.value = cacheCheckItems.value.concat([]);
  }

  updateCheckItems();
};

const onAllChange = () => {
  for (const item of props.items) {
    checkItemsMap.value[item[props.keyField]] = !isAllChecked.value;
  }
  cacheCheckItems.value = !isAllChecked.value ? props.items.concat([]) : [];
  updateCheckItems();
};

const onItemClose = (item) => {
  onItemChange(item);
};

const updateCheckItems = () => {
  isEffect = false;
  emit('update:checkItems', cacheCheckItems.value);
  nextTick(() => (isEffect = true));
};

const scrollContainer = ref();
const handleScroll = (e) => {
  const container = scrollContainer.value;
  console.log(
    e,
    container,
    container.scrollTop,
    container.clientHeight,
    container.scrollTop + container.clientHeight,
    container.scrollHeight,
    'e---------------',
  );
  if (container.scrollTop + container.clientHeight + 1 >= container.scrollHeight) {
    // 已经滚动到底部
    console.log('已经滚动到底部');
    // 在这里执行你的逻辑
    emit('on-scroll-end');
  }
};
</script>

<style lang="scss" scoped>
@mixin item() {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  box-sizing: border-box;
  // min-height: 52px;
  height: auto !important;
  border-bottom: 1px dashed #eee;
}

.virtual-scroll-checkout {
  width: 100%;
  display: flex;
  border: 1px solid var(--el-border-color);
  padding: 18px 0;
  box-sizing: border-box;
  border-radius: 4px;
}

.scroller-left,
.scroller-right {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  padding: 0 6px;
  min-width: 220px;
}

.scroller-right {
  border-left: 1px dashed var(--el-border-color);
  box-sizing: border-box;
}

.scroller-list-item {
  width: 100%;
  margin-right: 0px !important;
  @include item();

  :deep(.el-checkbox__label) {
    margin-left: 6px;
  }

  &:hover {
    background-color: var(--el-color-info-light-8);
    border-radius: 6px;
  }
}

.scroller-list {
  overflow-y: auto;
}

.scroller-list .is-checked.scroller-list-item {
  background-color: var(--el-color-info-light-8);
  border-radius: 4px;
}

.scroller-right-item {
  justify-content: space-between;

  &--left {
    flex: 1;
  }

  &--close {
    cursor: pointer;
    font-size: 14px;
  }
}

.scroller-all,
.scroller-select {
  height: 30px;
  flex-shrink: 0;
  @include item();
}
</style>
